"""
# -*- coding: utf-8 -*-
Time    : 2024/7/3 上午10:28
Author  : Micah
File    : excel处理对应关系.py
Function:
"""
import logging
import tkinter as tk
from tkinter import filedialog
import tkinter.messagebox
from openpyxl.reader.excel import load_workbook
import openpyxl
import re


def extract_dy_number(input_str):
    """
    输入一个字符串，如果字符串中包含'DY'后跟数字的模式，则返回该模式中的数字部分。
    如果没有找到匹配项，则返回None。
    """

    pattern = r'DY(\d+)'  # 定义正则表达式模式，括号表示捕获分组
    match = re.search(pattern, input_str)  # 在输入字符串中搜索匹配项

    if match:
        # 如果找到匹配项，返回匹配的数字部分
        return int(match.group(1))  # group(1)返回第一个捕获分组的内容
    else:
        return None  # 没有找到匹配项时返回None


def split_string_by_comma(input_string):
    """
    使用逗号将输入的字符串分割成列表。

    参数:
    input_string (str): 需要被分割的字符串。

    返回:
    list: 分割后的字符串列表。
    """
    # 使用str.split()方法，传入逗号作为分隔符
    return input_string.split(',')


def is_dy_number(s):
    """
    判断给定的字符串是否符合'DY'后跟任意数量的数字的模式。

    参数:
    s (str): 需要判断的字符串。

    返回:
    bool: 如果字符串符合'DY'数字模式，返回True；否则返回False。
    """
    pattern = r'^DY\d+$'  # 正则表达式，匹配以DY开头后面跟着一个或多个数字的字符串
    if s:
        return bool(re.match(pattern, s))
    else:
        return False


def consecutive_numbers_to_dx_string(lst):
    if not lst:  # 如果列表为空，直接返回空字符串
        return ""

    result_parts = []  # 存储最终的DX字符串片段

    start_num = lst[0]  # 记录连续序列的起始数字
    count = 1  # 计数器，记录连续数字的数量

    for num in lst[1:]:
        if num == start_num + count:  # 数字连续
            count += 1
        else:  # 数字不连续，处理并开始新的序列
            if count >= 3:  # 连续三个或以上数字
                result_parts.append(f"DX{start_num}~DX{start_num + count - 1}")
            elif count == 2:  # 连续两个数字
                result_parts.extend([f"DX{start_num}", f"DX{start_num + 1}"])
            else:  # 单个数字
                result_parts.append(f"DX{start_num}")
            start_num = num
            count = 1

    # 处理最后一个连续序列
    if count >= 3:  # 连续三个或以上数字
        result_parts.append(f"DX{start_num}~DX{start_num + count - 1}")
    elif count == 2:  # 连续两个数字
        result_parts.extend([f"DX{start_num}", f"DX{start_num + 1}"])
    else:  # 单个数字
        result_parts.append(f"DX{start_num}")

    # 将所有片段连接成一个字符串，各部分之间以逗号和空格分隔
    return result_parts


def compress_consecutive_numbers_final(input_str):
    # 分割并排序输入的DX数字序列
    dx_items = sorted([dx.strip() for dx in input_str.split(',') if dx.strip()])

    numbers_with_prefix = [
        int(nums[-1])  # 取最后一个数字
        for dx in dx_items
        if (nums := re.findall(r'\d+', dx))  # 使用 walrus 操作符来同时赋值和检查
    ]
    numbers_with_prefix.sort(reverse=False)

    result = consecutive_numbers_to_dx_string(numbers_with_prefix)

    return ','.join(result)


def add_dict_to_excel(file_path, sheet_name, data_dict):
    # 加载Excel工作簿
    wb = openpyxl.load_workbook(file_path)

    # 获取或创建指定的工作表
    if sheet_name not in wb.sheetnames:
        ws = wb.create_sheet(sheet_name)
    else:
        ws = wb[sheet_name]

    # 查找第一列和第四列的最后一个非空单元格的行号
    max_row_first_col = 1
    max_row_fourth_col = 1
    for row in ws.iter_rows(min_row=1, max_col=1, values_only=True):
        if row[0] is not None:
            max_row_first_col += 1
    for row in ws.iter_rows(min_row=1, max_col=4, values_only=True):
        if row[3] is not None:
            max_row_fourth_col += 1

    # 确定起始行号，取两者较大者，确保从空白处开始添加
    start_row = max(max_row_first_col, max_row_fourth_col)

    # 将字典数据添加到Excel中
    for key, value in data_dict.items():
        ws.cell(row=start_row, column=1, value=key)  # 第一列
        ws.cell(row=start_row, column=4, value=value)  # 第四列
        start_row += 1  # 移动到下一行

    # 保存工作簿
    wb.save(file_path)


def rewrite_dict_to_excel(file_path, sheet_name, data_dict):
    # 加载Excel工作簿
    wb = openpyxl.load_workbook(file_path)

    # 获取或创建指定的工作表
    if sheet_name not in wb.sheetnames:
        ws = wb.create_sheet(sheet_name)
    else:
        ws = wb[sheet_name]

    for row in ws.iter_rows(min_row=2, max_col=4, values_only=False):
        if is_dy_number(row[0].value):
            if row[0].value in data_dict:
                try:
                    row[3].value = data_dict[row[0].value]
                except:
                    row[3].value = 'wrong'
            else:
                row[3].value = 'N/A'

    # 保存工作簿
    wb.save(file_path)


def append_transformed_data(input_path):
    """
    读取Excel文件，转换每个sheet的第一列和第四列的对应关系，并将转换后的数据追加到新Excel文件的对应sheet中。

    参数:
    input_path (str): 输入Excel文件的路径。
    output_path (str): 输出（含追加数据）Excel文件的路径。
    """
    # 使用ExcelFile对象来处理多个sheet
    wb = load_workbook(input_path)

    # 用ExcelWriter创建一个新的Excel文件用于保存转换后的数据
    for sheet_name in wb.sheetnames:
        if 'Interlock' in sheet_name:
            sheet = wb[sheet_name]
            dict_data = {}
            # 读取单个sheet
            for row in sheet.iter_rows(min_row=1):  # 移除了values_only=True，以便我们可以访问到行号

                if 'DX' in str(row[0].value) and 'DY' in str(row[3].value):
                    lst_dy = split_string_by_comma(str(row[3].value))
                    for dy in lst_dy:
                        dy = extract_dy_number(dy)
                        if dy in dict_data:
                            dict_data[dy] += ',' + str(row[0].value)
                        else:
                            dict_data[dy] = str(row[0].value)
            # 先将字典的items转换为list，然后使用filter和lambda表达式来过滤出键为整数的条目
            filtered_items = filter(lambda item: isinstance(item[0], int), dict_data.items())

            # 对过滤后的条目进行排序
            sorted_list = sorted(filtered_items, key=lambda item: item[0])

            # 如果需要将排序后的键值对转换回字典，可以使用dict构造函数
            sorted_dict = dict(sorted_list)
            # 字典推导式，同时修改键和值
            for key, value in sorted_dict.items():
                sorted_dict[key] = compress_consecutive_numbers_final(value)

            sorted_dict = {f"DY{key}": value for key, value in sorted_dict.items()}

            # 保存工作簿
            rewrite_dict_to_excel(input_path, sheet_name, sorted_dict)


def select_file():
    """打开文件对话框选择Excel文件"""
    filepath = filedialog.askopenfilename(filetypes=[("Excel Files", "*.xlsx")])
    if filepath:
        try:
            append_transformed_data(filepath)
            tk.messagebox.showinfo("成功", "数据处理完成！")
        except Exception as e:
            tk.messagebox.showerror("错误", f"处理文件时出错：{str(e)}")
    else:
        tk.messagebox.showinfo("提示", "未选择文件！")


if __name__ == '__main__':
    try:
        # 创建UI
        root = tk.Tk()
        root.title("Interlock List 文件处理器")
        root.geometry("300x100")
        select_button = tk.Button(root, text="选择Excel文件", command=select_file)
        select_button.pack()

        root.mainloop()
    except Exception as e:
        logging.error(f"UI创建失败：{str(e)}")
